package com.virtualparadigm.identity;

import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;

import com.virtualparadigm.hierarchy.LineageList;
import com.virtualparadigm.hierarchy.LineageListParser;

public abstract class ResourceAddress implements Serializable
{
	private static final long serialVersionUID = 1L; 
//	private String scheme;
	private LineageList<String> namespace; 
	private LineageList<ResourcePathElement> path; 
	
	//URI is being used mainly to validate the input
	private URI uri; 
	
	public ResourceAddress(
			LineageList<String> namespace, 
			LineageList<ResourcePathElement> path) 
	{
		super();
		try
		{
			if(namespace == null || path == null || namespace.getSize() != path.getSize())
			{
				throw new IllegalArgumentException("namespace and path must be non null and have same size");
			}
			
			this.uri = 
					new URI(
							this.getScheme(), 
							LineageListParser.toString(namespace, ".", false), 
							"/" + LineageListParser.toString(path, "/", true), 
							null);
			
			this.namespace = (LineageList<String>)namespace.clone();
			this.path = (LineageList<ResourcePathElement>)path.clone();
		}
		catch(URISyntaxException urise)
		{
			urise.printStackTrace();
			throw new IllegalStateException("could not inialize resource locator", urise);
		}
		catch(CloneNotSupportedException cnse)
		{
			cnse.printStackTrace();
			throw new IllegalStateException("could not inialize resource locator", cnse);
		}
		catch(Exception e)
		{
			e.printStackTrace();
			throw new IllegalStateException("could not inialize resource locator", e);
		}
	}
	
	public ResourceAddress(String str) 
	{
		if(str != null && !str.startsWith(this.getScheme() +":"))
		{
			throw new IllegalStateException("invalid scheme. could not inialize resource locator");
		}
		
		try
		{
			this.uri = new URI(str);
			this.namespace = LineageListParser.parse(uri.getAuthority(), ".", false);
			LineageList<String> parsedLineageList = LineageListParser.parse(uri.getPath(), "/", true); 
			if(parsedLineageList != null)
			{
				this.path = new LineageList<ResourcePathElement>();
//				this.path.queueChild(new ResourcePathElement(parsedLineageList.popParent()));
			}

			if(this.namespace == null || this.path == null || this.namespace.getSize() != this.path.getSize())
			{
				throw new IllegalArgumentException("namespace and path must be non null and have same size");
			}
		}
		catch(URISyntaxException urise)
		{
			urise.printStackTrace();
			throw new IllegalStateException("could not inialize resource locator", urise);
		}
		catch(Exception e)
		{
			e.printStackTrace();
			throw new IllegalStateException("could not inialize resource locator", e);
		}
	}
	
	public LineageList<String> getNamespace()
	{
		return namespace;
	}
	public LineageList<ResourcePathElement> getPath()
	{
		return path;
	}

	public URI getURI()
	{
		return this.uri;
	}
	
	public String toString()
	{
		return this.getURI().toString();
	}
	
	// =================================================
	// ABSTRACT METHODS
	// =================================================
	abstract String getScheme();
	
}